#import "MapViewController.h"

/**
 * This class represents the main view of the application. 
 *
 * It is responsible for displaying the map view and all its elements. Such elements 
 * include: annotations, callout bubbles, and the users current location.
 *
 * Event and Building search events are handled within this class.
 * 
 * @author      Justin Hollander
 * @version     0.9.5
 * @since       0.1.0
 * @see         MapBuildingSearchDelegate
 * @see         SFUEventSearchResponseDelegate
 */
@implementation MapViewController

@synthesize mapView;
@synthesize mapTabBar;
@synthesize searchItem;
@synthesize settingsItem;
@synthesize bookmarksItem;
@synthesize isBuildingSearch;

/**
 * Initializes the view controllers subviews.
 */
-(void) initWindowObjects{
	//x,y,width,height
	mapView = [[MKMapView alloc] initWithFrame:CGRectMake(ZERO, ZERO, VIEW_WIDTH, MAP_VIEW_HEIGHT)];
	mapView.scrollEnabled = YES;
	mapView.zoomEnabled = YES;
 
	self.mapTabBar = [[UITabBar alloc] initWithFrame:CGRectMake(ZERO, MAP_VIEW_HEIGHT, VIEW_WIDTH, TAB_BAR_WIDTH)];
	searchItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemSearch tag:2];
	//settingsItem = [[UITabBarItem alloc] initWithTitle:@"Settings" image:nil tag:0];
	bookmarksItem = [[UITabBarItem alloc] initWithTitle:@"Bookmarks" image:nil tag:1];
	[mapTabBar setItems:[NSArray arrayWithObjects:bookmarksItem, searchItem, nil] animated:YES];
	
}

/**
 * Converts our userdefined GPSLocation into a MKMapView supported point location type
 *
 * @param   gps                     userdefined type encapsulating the coordinates of a location 
 * @return  CLLocationCoordinate2D  the MKMapView supported type for a point location
 */
-(CLLocationCoordinate2D) addressLocation:(GPSLocation*)gps {
	
	CLLocationCoordinate2D location;
	location.latitude = gps.latitude;
	location.longitude = gps.longitude;
	
	return location;
}

/**
 * Physically attempts to put the building
 *
 * @param b  Building location to be shown on the map
 */
- (void) showAddress:(Building*)b {
	
	MKCoordinateRegion region;
	MKCoordinateSpan span;
	span.latitudeDelta=0.005;
	span.longitudeDelta=0.005;
	
	CLLocationCoordinate2D location = [self addressLocation:b.loc];
	
	region.span=span;
	region.center=location;
	
	addAnnotation = [AddressAnnotation mapAnnotationWithCoordinate:location 
														  andTitle:b.name 
													   andSubtitle:(self.isBuildingSearch)? @"" : @"Touch to view events"];
	
	[mapView addAnnotation:addAnnotation];
	
	[mapView setRegion:region animated:TRUE];
	[mapView regionThatFits:region];
	//[mapView selectAnnotation:mLodgeAnnotation animated:YES];
}

/**
 * Wrapper to display a building on the map
 *
 * @param buildingToDisplay Reference to the building that will be displayed
 */
-(void) displayBuilding:(Building*) buildingToDisplay{
	[self showAddress:buildingToDisplay];
}

/**
 * Removes all active annotations from the map except for the user location.
 */
-(void) removeActiveAnnotation{
	
	
	NSArray* buildingList = [[BuildingCollection sharedBuildingCollection] getDataTypes];
	NSMutableArray *toRemove = [NSMutableArray arrayWithCapacity:10]; //list of annotations
	for (id annotation in self.mapView.annotations)
		if (annotation != self.mapView.userLocation) //not current location ??
			[toRemove addObject:annotation]; //remove annotation
	[self.mapView removeAnnotations:toRemove];
	
	for(id annotation in toRemove){ //free annotations
		[annotation release];
		
		for(Building* b in buildingList){ //free temporary building event lists
			if (b.eventList != nil) {
				[b.eventList removeAllObjects];
				[b.eventList release];
				b.eventList = nil;
			}
		}
		
	}
	
}

/**
 * Processes a search request.
 *
 * If it is a building search then the callout bubble have veiwable event information
 * else it will contain viewable event information by way of a button
 * 
 * @param building  the building to be displayed
 */
- (void)searchRequestByBuilding:(Building*)building isNew:(BOOL)isNew{
	NSLog(@"Search for %@", building.name);
	self.isBuildingSearch = YES;
	if (isNew) { //invalidate view ??
		[self removeActiveAnnotation];
	}
	if (building != nil) {
		[self displayBuilding:building];
	}
}

/**
 * Assign each matchded event to its building location
 *
 * The events event location is matched with the name of the building.
 * Each matching event is then added to a buildings eventList.
 * 
 * @param matchedEventsWithLocations event matches from event search
 */
-(void) mapMatchedEventsByBuilding:(NSArray*)matchedEventsWithLocations{
	BuildingCollection* bc = [BuildingCollection sharedBuildingCollection];
	NSArray* buildingList = [bc getDataTypes];
	
	
	for(SFUEvent* matchedEvent in matchedEventsWithLocations){
		for(Building* building in buildingList){
			if ([building.name isEqualToString:matchedEvent.eventLocation] ) {
				if(building.eventList == nil)
					building.eventList = [[NSMutableArray alloc] init];
				[building.eventList addObject:matchedEvent];
				break;
			}
		}
	}
	
}

/**
 * Receives the set of event matches generated by an event search and dispays them
 *
 * If zero matches are contained within the collection then an alert is shown indicating
 * this state.
 *
 * @param eventMatches  array of matching events
 * @see SFUEventSearchResponseDelegate
 */
-(void) eventResponseBySearchSuccess:(NSArray*)  eventMatches{

	NSArray* buildingList = [[BuildingCollection sharedBuildingCollection] getDataTypes];
	[self removeActiveAnnotation];
	self.isBuildingSearch = NO;
	if (eventMatches != nil) {
		
		if ([eventMatches count] == 0) { //search yielded no results ??
			UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:@"No matching events found." 
																 message:@"" 
																delegate:self 
													   cancelButtonTitle:@"Ok" 
													   otherButtonTitles:nil] autorelease];
			[alertView show];
			return;
		}
		else {
			NSLog(@"count: %d",[eventMatches count]);
			BOOL allNull = YES;
			for(SFUEvent* e in eventMatches){
				if(e.eventLocation != nil){
					allNull = NO;
					break;
				}
			}
			
			if(allNull)
			{
				UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:@"No matching events found." 
																	 message:@"" 
																	delegate:self 
														   cancelButtonTitle:@"Ok" 
														   otherButtonTitles:nil] autorelease];
				[alertView show];
				return;
			}
				
				
		}

		
		[self mapMatchedEventsByBuilding:eventMatches]; //assign each event to its location
														//on campus

		//display events
		for (Building* building in buildingList) {
			if ([building.eventList count] > 0 ) {
				//self.eventArray = building.eventList;
				[self displayBuilding:building];
			}
		}
	}
}

/**
 * Handles incoming tabBar events and sends the corresponding message
 *
 * @param tabBar         a reference to this views tabbar
 * @param didSelectItem  selected item on the tabBar
 */
-(void) tabBar:(UITabBar*)tabBar didSelectItem:(UITabBarItem*)item{
	
	switch (item.tag) {
		case 0:
			NSLog(@"you are trying to settings");
			break;
		case 1:
			[self performSelector:@selector(handleBookmarks)];
			break;
		case 2:
			[self performSelector:@selector(handleSearch)];
			break;
		default:
			break;
	};
}

/**
 * Receives the set of event matches generated by an event search
 * 
 * @param msg reason for failure
 * @return void
 * @see SFUEvnetSearchResponseDelegate
 */
-(void) eventResponseBySearchFailure:(NSString*) msg{
	UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:@"Error" 
														 message:msg
														delegate:self 
											   cancelButtonTitle:@"Ok" 
											   otherButtonTitles:nil] autorelease];
	[alertView show];
}

/**
 * Adds subviews to this view controller
 */
-(void) addViews{
	[self.view addSubview:mapView];
	[self.view addSubview:mapTabBar];
}

/**
 * Registers view conrtoller as delegate to the tabbar, map view and event manager
 */
-(void) registerDelegates {
	[mapTabBar setDelegate:self];
	[mapView setDelegate:self];
	[[EventManager sharedEventManager] setViewBuildingDelegate:self];
}

/**
 * Activates the search list viewer upon touching the search tab item
 */
-(void) handleSearch{
	//[self removeActiveAnnotation];
	
	MapSearchListViewer* mslv = [MapSearchListViewer sharedMapSearchListViewer];
	[mslv displayWithNavController:self.navigationController 
				bldgSearchDelegate:self 
			   eventSearchDelegate:self];
}

/**
 * Activates bookmark view on bookmark selection within the tab bar
 */
-(void) handleBookmarks{
	EventManager* em = [EventManager sharedEventManager];
	self.isBuildingSearch = NO;
	if (![em displayBookmarkedWithNavController:[self navigationController]]) {
		mapTabBar.selectedItem = nil;
	}
	
}

/**
 * Constructor for MapViewController
 * 
 * @return id  a reference to the instance of this class
 */
-(id) init{
	if (self=[super init]) {
		[self initWindowObjects];
		[self registerDelegates];
		[self addViews];
		
		
		// Make the building collection data file
		[BuildingDataUtility buildBuildingData];		
	}
	return self;
}

/**
 * Displays event iformation off the callout bubbles button
 */
-(void) showEventDetails {
	
	NSArray* annotations = [self.mapView selectedAnnotations];
	
	if(annotations != nil){
	
		for(id<MKAnnotation> ann in annotations){
			Building* b = [ParsingUtilities parseBuildingFromString:ann.title]; //find the matching building
			if (b != nil) {
				
				[[EventManager sharedEventManager] displayEvents:[b eventList]  //display buildings event list
												   navController:[self navigationController]];
			}
		}
	}
	
}

/**
 * Everytime this view controllers view loads ensures that its navigation bar
 * is hidden in an animated fashion for smoothness
 *
 */
-(void) viewWillAppear:(BOOL)animated {
	[[self navigationController ] setNavigationBarHidden:YES animated:YES];
	mapTabBar.selectedItem = nil;
	[super viewWillAppear:animated];
}

/**
 * Everytimew we unload the view viewController we need to 
 * make the navigation 
 *
 */
-(void) viewWillDisappear:(BOOL)animated {
	self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
	[[self navigationController ] setNavigationBarHidden:NO animated:YES];
	[super viewWillDisappear:animated];
}


-(void) viewDidLoad {
	[super viewDidLoad];
	MKCoordinateRegion region;
	MKCoordinateSpan span;
	span.latitudeDelta=DEFAULT_SPAN;
	span.longitudeDelta=DEFAULT_SPAN;
	CLLocationCoordinate2D location;
	location.latitude = DEFAULT_LATITUDE;
	location.longitude = DEFAULT_LONGITUDE;
	region.span = span;
	region.center = location;
	[mapView setRegion:region animated:TRUE]; //sets the default zoom and location on the map on startup
	[mapView regionThatFits:region];
	[self.navigationController.navigationBar setHidden:YES]; //no need to see nav bar in map
	self.mapView.showsUserLocation = YES; //enable and view user location annotation
}

/**
 * See apple API.
 * MKMapViewDelegate.viewForAnnotation
 */
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{

	//CustomPin* pinView = nil;
	MKPinAnnotationView *pinView = nil;	
	
	if(annotation != self.mapView.userLocation) {
		//AddressAnnotation *annotation = (AddressAnnotation*)annotation;
		pinView = (MKPinAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"currentloc"];
		if(nil == pinView) {
			//NSString* path = [FileUtilities getResource:@"buildingPin.png"];
			//pinView = [[[CustomPin alloc] initWithDetails:annotation 
			//									imagePath:path] autorelease];
			pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
													   reuseIdentifier:@"currentloc"] autorelease];

		}
		[pinView setPinColor: MKPinAnnotationColorRed];
		[pinView setAnimatesDrop: YES]; 
		[pinView setCanShowCallout: YES];
		
		if(!self.isBuildingSearch) {
			UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
			[rightButton addTarget:self	
							action:@selector(showEventDetails) 
				  forControlEvents:UIControlEventTouchUpInside];
			[pinView setRightCalloutAccessoryView:rightButton];
		}
		else {
			[pinView setRightCalloutAccessoryView:nil];
		}

	}
	
	return pinView;
}

- (void)dealloc {
	[mapView release];
	[mapTabBar release];
	[searchItem release];
	[bookmarksItem release];
	[[BuildingCollection sharedBuildingCollection] dealloc];
    [super dealloc];
}


@end
